<template>
  <div class="v-editor-value-specification g-flex">
    <div class="g-pd-l-8 g-flex-1 g-flex-left">
      <template v-if="element">
        <span v-if="encrypted">{{ desensitize(element.name) }}</span>
        <template v-else>
          <img
            class="g-m-r-4 g-relative g-t-2"
            style="top: -1px; height: 16px"
            :src="element.icon"
          />
          <span v-if="element.name">{{ element.name }}</span>
        </template>
      </template>

      <template v-else>
        <!-- 根据数据类型渲染输入框 -->
        <div
          v-if="[MetaclassType.LiteralString,MetaclassType.OpaqueExpression,MetaclassType.StringExpression,MetaclassType.LiteralUnlimitedNatural].includes(inputType as MetaclassType)"
        >
          <span v-if="encrypted">
            <span v-if="containTermName.length">
              <span
                v-for="(item, index) in containTermName"
                :key="index"
              >
                <span
                  v-if="item.isTerm"
                  class="show-underline"
                  @contextmenu.stop="event => showDetailTerm(event, item.name)"
                >
                  {{ item.name }}
                </span>
                <span v-else>{{ item.name }}</span>
              </span>
            </span>
            <span v-else>{{ desensitize(inputValue) }}</span>
          </span>
          <div v-else>
            <div
              v-if="!isFocus && containTermName.length"
              style="width: 100%; cursor: text"
              @click="handleTermClick"
            >
              <span
                v-for="(item, index) in containTermName"
                :key="index"
              >
                <span
                  v-if="item.isTerm"
                  class="show-underline"
                  @contextmenu.stop="event => showDetailTerm(event, item.name)"
                >
                  {{ item.name }}
                </span>
                <span v-else>{{ item.name }}</span>
              </span>
            </div>
            <el-input
              v-else
              ref="inputRef"
              v-model="inputValue"
              :disabled="isModelDisabled"
              @change="handelInputChange"
              @focus="handleFocus"
              @blur="handleBlur"
            />
          </div>
        </div>
        <div
          v-else-if="inputType === MetaclassType.LiteralInteger || inputType === MetaclassType.LiteralReal"
          class="g-w-100"
        >
          <span v-if="encrypted">{{ desensitize(inputValue) }}</span>
          <FormatScientificNumber
            v-else
            :inputValue="inputValue"
            :controls="false"
            :min="minNum"
            :max="maxNum"
            :disabled="isModelDisabled"
            :config="{
              scientificNotation: visibleTableData.scientificNotation,
              precisionLimit: visibleTableData.precisionLimit,
              precision: visibleTableData.precision
            }"
            @change="handelInputChange as any"
          />
        </div>
        <div v-else-if="inputType === MetaclassType.LiteralBoolean">
          <span v-if="encrypted">{{ "*" }}</span>
          <el-checkbox
            v-else
            v-model="inputValue"
            :disabled="isModelDisabled"
            @change="handelInputChange"
          >
            {{ inputValue ? "是" : "否" }}
          </el-checkbox>
        </div>
        <div v-else-if="inputType === MetaclassType.LiteralNull">
          <span v-if="encrypted">{{ "*" }}</span>
          <span v-else>Null</span>
        </div>
        <div v-else></div>
      </template>
    </div>

    <div
      v-if="selected && !row.readonly && !isModelDisabled"
      class="g-pd-r-4 g-flex-0 g-flex-center"
    >
      <template v-if="!isEnums">
        <span
          v-if="inputType === MetaclassType.ElementValue || inputType === MetaclassType.InstanceValue"
          class="g-m-r-4"
        >
          <img
            src="statics/icons/app/iconmore.png"
            class="g-pointer"
            @click="chooseElement(inputType as MetaclassType)"
          />
        </span>
        <span
          v-else-if="inputType === MetaclassType.OpaqueExpression"
          class="g-m-r-4"
        >
          <img
            src="statics/icons/app/iconmore.png"
            class="g-pointer"
            @click="chooseCodeLanguage"
          />
        </span>
        <span class="g-m-r-4 _select_lable">{{ selectedLabel }}</span>
      </template>
      <MDropdown
        class="g-inline-block"
        lazy
        :loadListCallback="loadOptions"
      >
        <div>
          <img
            src="statics/icons/app/iconlist2.png"
            class="g-pointer"
            @click="handleClick"
          />
        </div>
        <template #dropdown>
          <MDropdownMenuItem
            v-if="props.row.value"
            @click="handleDelete"
          >
            <template v-if="isEnums">
              <span class="v-editor-value-specification-empty-block"></span>
              <span class="g-pd-lr-8">{{ $t("空") }}</span>
            </template>
            <template v-else>
              <img
                src="statics/icons/app/icondelete4.png"
                style="height: 16px"
              />
              <span class="g-pd-lr-8">{{ $t("删除") }}</span>
            </template>
          </MDropdownMenuItem>
          <MDropdownMenuItem
            v-for="(item, index) in specificationValues"
            :key="index"
            @click="handleClickOption(item)"
          >
            <img
              :src="item.icon"
              style="width: 16px; height: 16px"
            />
            <span class="g-pd-lr-8">{{ locale.value === "en" ? item.value : item.label }}</span>
          </MDropdownMenuItem>
        </template>
      </MDropdown>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { actionManager } from "@/action/ActionManager";
import { CreatePropertyModelTreeSelect } from "@/modules/model/actions/project/CreatePropertyModelTreeSelect";
import { PropertyRow, UpdateValueSpecificationDto } from "../../types";
import { ref, Ref, computed, watch, toRaw, inject, nextTick } from "vue";
import MDropdown from "@/common/dropdown/Dropdown.vue";
import MDropdownMenuItem from "@/common/dropdown/DropdownMenuItem.vue";
import { propertyUtil } from "../../PropertyUtil";
import { MetaclassType } from "@/constants/MetaclassType";
import { valueSpecificationTypes, ValueSpecificationType, instanceValueSpecificationTypes } from "./ValueSpecificationTypes";
import { stepMessageHandler } from "@/modules/model/socket/StepMessageHandler";
import { desensitize, sleepUntil } from "@/util/common";
import LanguagePopup from "./LanguagePopup.vue";
import { ActionKey } from "@/action/ActionKey";
import { locale } from "@/util/locale";
import { showDetailTermCommon } from "@/modules/model/service/termBankService";
import { ContainTermName, splitOriginTextWithTerms } from "@/mdesign-lib/mdesign-graph.umd.js";
import { ElInput } from "element-plus";
import { useLoadItemsOptions } from "./useLoadOptions";
import { PropertyItemType } from "@/constants/constants";
import FormatScientificNumber from "@/modules/model/comps/common/FormatScientificNumber.vue";
import { PropertyDataType } from "@/constants/Enums";

const isModelDisabled = inject("isModelDisabled") as Ref<boolean>;

/**
 * 右侧有个下拉菜单，选择模型类型
 */
const props = defineProps<{
  row: PropertyRow;
  selected?: boolean;
  encrypted?: boolean;
  isInstance?: boolean;
}>();
const emit = defineEmits<{
  (e: "inputChange", value: string, type: MetaclassType): void;
}>();
const element = computed(() => {
  return props.row.valueSpecificationInfo?.element;
});
const inputType = computed(() => {
  return props.isInstance ? valueType.value : props.row.valueSpecificationInfo?.metaclass;
});

const isFocus = ref(false);

const inputRef = ref<InstanceType<typeof ElInput>>();

const inputValue = ref<any>(props.row.valueSpecificationInfo?.value);

const valueType = ref(props.row.valueSpecificationInfo?.metaclass);
const options = ref<any>();
const loadOptions = ref<any>();

const isEnums = computed(() => {
  // const items = props.row.items || [];
  // props.row.itemType === PropertyItemType.items 判断是否为枚举
  return !!(props.row.itemType === PropertyItemType.items && props.row.dataType === PropertyDataType.INSTANCE);
});

const attributeTabsModel = computed(() => app.activeProject?.attributeTabsModel);
const visibleTableData = computed(() => {
  if (!attributeTabsModel.value) return {};

  const data = attributeTabsModel.value.propertyPaneModel.getVisibleTableData();
  const dataMap = Object.fromEntries(data.map(({ name, value }) => [name, value]));

  return {
    scientificNotation: dataMap["scientificNotation"],
    precisionLimit: dataMap["precisionLimit"],
    precision: dataMap["precision"]
  };
});

watch(
  () => props.row.modelId,
  (val: string) => {
    if (val) {
      const res = useLoadItemsOptions(props.row);
      options.value = res.options;
      loadOptions.value = res.loadOptions;
    }
  },
  { immediate: true }
);

const specificationValues = computed(() => {
  const newValue =
    !!options.value.value &&
    options.value.value.map(it => {
      return {
        value: it.value,
        label: it.label,
        icon: it.icon,
        default: it.value
      } as ValueSpecificationType;
    });
  let values = isEnums.value ? newValue : valueSpecificationTypes;
  if (props.isInstance) {
    values = instanceValueSpecificationTypes;
  }
  return values;
});

const selectedLabel = computed(() => {
  let info = valueSpecificationTypes.find(item => item.value == props.row.valueSpecificationInfo?.metaclass);
  if (props.isInstance) {
    info = valueSpecificationTypes.find(item => item.value == valueType.value);
  }
  return locale.value === "en" ? info?.value : info?.label;
});

const maxNum = computed(() => {
  // const metaclass = props.row.valueSpecificationInfo?.metaclass;
  // switch (metaclass) {
  //   case MetaclassType.LiteralUnlimitedNatural:
  //   case MetaclassType.LiteralInteger:
  //     return 2147483647;
  //   case MetaclassType.LiteralReal:
  //     return 2147483647;
  //   default:
  //   }
  return 1.7976931348623157 * Math.pow(10, 308);
});

const containTermName = computed(() => {
  let _containTermName: ContainTermName[] = [];
  if (props.row.valueSpecificationInfo?.metaclass === MetaclassType.LiteralString) {
    _containTermName = splitOriginTextWithTerms(
      (props.row.valueSpecificationInfo?.value as string) || "",
      props.row.valueSpecificationInfo?.terms || []
    );
  }
  return _containTermName;
});

const minNum = computed(() => {
  const metaclass = props.row.valueSpecificationInfo?.metaclass;
  if (metaclass === MetaclassType.LiteralUnlimitedNatural) {
    return 0;
  }
  return -1.7976931348623157 * Math.pow(10, 308);
});

watch(
  () => props.row.valueSpecificationInfo?.value,
  val => {
    inputValue.value = val;
    checkValue();
  }
);
const clientY = ref(0);
const handleClick = (target: MouseEvent) => {
  clientY.value = target.clientY;
};
function checkValue() {
  if (inputType.value === MetaclassType.LiteralBoolean && typeof props.row.valueSpecificationInfo?.value !== "boolean") {
    console.error("数据错误valueSpecificationInfo.value不是boolean值", props.row.valueSpecificationInfo);
  }
}
checkValue();

async function handleClickOption(option: ValueSpecificationType) {
  if (option.value === props.row.valueSpecificationInfo?.metaclass) {
    return;
  }
  if (props.isInstance) {
    valueType.value = option.value;
    return option.value;
  }

  let instanceId = props.row.modelId; // ValueSpecification的父ID
  // const propertyKeyGuards = [PropertyKey.Transition_guard, PropertyKey.Message_guard];
  // if (propertyKeyGuards.includes(props.row.key as PropertyKey)) {
  // if (props.row.valueSpecificationInfo?.elementId) {
  //   // 若是转换的守卫则UpdateValueSpecificationDto的instanceId 应该是约束的ID
  //   instanceId = props.row.valueSpecificationInfo?.elementId;
  // }
  // }
  const updateValueSpecification: UpdateValueSpecificationDto = {
    // 创建值模型参数
    extraValue: "",
    value: option.default,
    instanceId: instanceId,
    metaclass: isEnums.value ? MetaclassType.InstanceValue : option.value,
    projectId: app.activeProject!.config.id,
    valueSpecificationId: "",
    key: props.row.key
  };
  let nextStepPromise: Promise<any> | undefined = undefined;
  if (option.value === MetaclassType.InstanceValue || option.value === MetaclassType.ElementValue) {
    nextStepPromise = stepMessageHandler.waitNextStep();
  }
  let arr: Promise<any>[] = [];
  if (nextStepPromise) {
    arr.push(nextStepPromise);
  }
  const p2 = propertyUtil.updatePropertyAndFresh(props.row, option.value, false, updateValueSpecification);

  arr.push(p2);
  await Promise.all(arr);
  if (option.value === MetaclassType.InstanceValue || option.value === MetaclassType.ElementValue) {
    await sleepUntil(() => !!props.row.valueSpecificationInfo);
    chooseElement(option.value);
  }
}

async function handleDelete() {
  if (props.isInstance) {
    valueType.value = undefined;
    inputValue.value = "";
    return;
  }
  if (isEnums.value) {
    let instanceId = props.row.modelId;
    const updateValueSpecification: UpdateValueSpecificationDto = {
      // 创建值模型参数
      extraValue: "",
      value: "",
      instanceId: instanceId,
      metaclass: isEnums.value ? "ElementValue" : "",
      projectId: app.activeProject!.config.id,
      valueSpecificationId: "",
      key: props.row.key
    };
    await propertyUtil.updatePropertyAndFresh(props.row, "", false, updateValueSpecification);
  } else {
    if (props.row.value) {
      if (Array.isArray(props.row.value)) {
        props.row.value = props.row.value.last();
      }
      await propertyUtil.deletePropertyAndRefresh(props.row, props.row.value as string);
    }
  }
}

async function handelInputChange(value: string | number | boolean) {
  if (Array.isArray(props.row.value)) {
    props.row.value = props.row.value.last();
  }
  if (props.isInstance && inputType.value) {
    emit("inputChange", inputValue.value, inputType.value);
    return;
  }
  const updateValueSpecification: UpdateValueSpecificationDto = {
    // 创建值模型参数
    extraValue: props.row.valueSpecificationInfo?.extraValue || "",
    value: value,
    instanceId: props.row.modelId,
    metaclass: props.row.valueSpecificationInfo?.metaclass,
    projectId: app.activeProject!.config.id,
    valueSpecificationId: props.row.value as string,
    key: props.row.key
  };
  await propertyUtil.updatePropertyAndFresh(props.row, props.row.value, false, updateValueSpecification);
}

async function chooseElement(selectedType: MetaclassType) {
  const row = props.row;
  let moreBtnCondition = "";

  if (selectedType === MetaclassType.InstanceValue) {
    // 实例值只能选实例
    moreBtnCondition = MetaclassType.InstanceSpecification;
  } else if (selectedType === MetaclassType.ElementValue) {
    // 元素值可以选所有的element
    moreBtnCondition = MetaclassType.Element;
  }
  const action = actionManager.getAction(ActionKey.CreatePropertyModelTreeSelect) as CreatePropertyModelTreeSelect;
  const row2 = toRaw(row);
  row2.valueSpecificationInfo && (row2.valueSpecificationInfo.metaclass = selectedType);
  action.run({
    ...row2,
    moreBtnCondition
  });
}

function chooseCodeLanguage() {
  const res = LanguagePopup.popup({
    row: props.row
  });
  console.log(res);
}

const handleFocus = () => {
  isFocus.value = true;
};
const handleBlur = () => {
  isFocus.value = false;
};
const handleTermClick = () => {
  isFocus.value = true;
  nextTick(() => {
    inputRef.value!.focus();
  });
};

function showDetailTerm(event: MouseEvent, termText: string) {
  if (props.row.readonly || isModelDisabled?.value) return;
  showDetailTermCommon(event, termText);
}
</script>
<style lang="scss">
.v-editor-value-specification {
  .el-input-number.is-without-controls {
    .el-input__wrapper {
      padding-right: 0px;
      padding-left: 0px;
      box-shadow: none;
      background: inherit;
      height: 24px;
      font-size: 11px;
      .el-input__inner {
        padding-right: 0px;
        padding-left: 0px;
      }
    }
  }

  ._select_lable {
    align-self: center;
  }
  .el-input-number--small {
    width: 100%;
    min-width: 20px;
  }
  .el-input-number {
    width: 100%;
  }
}
.v-editor-value-specification-empty-block {
  width: 16px;
  display: block;
  height: 16px;
  margin-right: 4px;
}
</style>
